home *** CD-ROM | disk | FTP | other *** search
- NAME MSNUT1
- ; File MSNUT1.ASM
- ; Provides various Intel 8088 level operations, including
- ; display facilities (via msg buffer or DOS) for char, strings, etc.
- ;
- ; Copyright 1991, University of Waterloo.
- ; Copyright (C) 1985, 1993, Trustees of Columbia University in the
- ; City of New York. Permission is granted to any individual or institution
- ; to use this software as long as it is not sold for profit. This copyright
- ; notice must be retained. This software may not be included in commercial
- ; products without written permission of Columbia University.
- ;
- ; Written by Erick Engelke of the University of Waterloo, Waterloo,
- ; Ontario, Canada,
- ; and by Joe R. Doupnik, Utah State University,
- ; jrd@cc.usu.edu, jrd@usu.Bitnet.
- ;
- ; Edit history
- ; 27 August 1992 version 3.13
- ; 6 Sept 1991 v3.11
- ; Last Edit
- ; 13 May 1993
-
- cr equ 0dh
- lf equ 0ah
- conout equ 2
- dos equ 21h
- allocmem equ 48h
- freemem equ 49h
-
- MSGBUFLEN equ 512 ; coordinate with msntnd.c
- BIOSCLK equ 046ch
- HI_MAX equ 018h
- LO_MAX equ 0b0h
-
- _TEXT SEGMENT WORD PUBLIC 'CODE'
- _TEXT ENDS
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
- CONST SEGMENT WORD PUBLIC 'CONST'
- CONST ENDS
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- DGROUP GROUP CONST, _BSS, _DATA
- ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
-
- _DATA SEGMENT
- extrn _doslevel:word, _msgcnt:word, _msgbuf:byte,_display_mode:byte
- _DATA ENDS
-
- _TEXT segment
-
- ; Compute 1's-complement sum of data buffer
- ; unsigned checksum( unsigned word *buf, unsigned cnt)
-
- public _checksum
- _checksum proc near
- push bp
- mov bp,sp
- push si
- push bx
- push cx
- push dx
- mov si,[bp+4+0] ; offset of data to be checked
- mov cx,[bp+4+2] ; cx = cnt
- mov bl,cl
- shr cx,1 ; group into words
- xor dx,dx ; set checksum to 0
- cld
- jcxz chk3
- clc
- chk1: lodsw
- adc dx,ax
- loop chk1
- ; resolve remainder
- chk2: adc dx,0
- jc chk2
- chk3: and bl,1
- jz chk5
- xor ah,ah
- lodsb
- clc
- add dx,ax
- chk4: adc dx,0
- jc chk4
- chk5: mov ax,dx ; result into ax
- or ax,ax
- jnz chk6
- mov ax,0ffffh
- chk6: pop dx
- pop cx
- pop bx
- pop si
- pop bp
- ret
- _checksum endp
-
- ; ntohl(longword x) 32 bit network (big endian) to host (little endian)
- ; htonl(longword x) 32 bit host (little endian) to network (big endian)
- ; intel(longword x)
- ; Reverse order of 4 byte groups between big and little endian forms
- ;
- public _intel, _ntohl, _htonl
-
- _intel proc near
- _ntohl equ this byte
- _htonl equ this byte
- push bp
- mov bp,sp
- mov ax,[bp+4+2]
- mov dx,[bp+4+0]
- xchg al,ah
- xchg dl,dh
- pop bp
- ret
- _intel endp
-
- ; ntohs(word x) 16 bit network (big endian) to host (little endian)
- ; htons(word x) 16 bit host (little endian) to network (big endian)
- ; intel16(word x)
- ; Reverse order of 2 byte groups between big and little endian forms
- public _intel16, _ntohs, _htons
- _intel16 proc near
- _ntohs equ this byte
- _htons equ this byte
- push bp
- mov bp,sp
- mov ax,[bp+4+0]
- xchg al,ah
- pop bp
- ret
- _intel16 endp
-
-
- ; int ourmod(int top, int bottom)
- ; Perform modulo function on 16 bit quantities
- public _ourmod
- _ourmod proc near
- push bp
- mov bp,sp
- push bx
- mov ax,[bp+4+0] ; top number
- mov bx,[bp+4+2] ; bottom number (radix)
- xor dx,dx
- or bx,bx ; bottom is zero?
- jz ourmod1 ; z = yes, return zero
- div bx
- ourmod1:mov ax,dx ; return remainder
- pop bx
- pop bp
- ret
- _ourmod endp
-
- ; int ourdiv(int top, int bottom)
- ; Perform 16 bit integer division
- public _ourdiv
- _ourdiv proc near
- push bp
- mov bp,sp
- push bx
- mov ax,[bp+4+0] ; top
- mov bx,[bp+4+2] ; bottom
- xor dx,dx
- or bx,bx ; divide by zero?
- jz outdiv1 ; z = yes, divide by one
- div bx
- outdiv1:pop bx
- pop bp ; quotient is returned in ax
- ret
- _ourdiv endp
-
- ; int ourlmod(long top, int bottom)
- ; Perform 32 bit integer modulo function
- public _ourlmod
- _ourlmod proc near
- push bp
- mov bp,sp
- push bx
- mov ax,[bp+4+0] ; top lower 16 bits
- mov dx,[bp+4+2] ; top upper 16 bits
- mov bx,[bp+4+4] ; bottom
- or bx,bx ; zero?
- jz outlmo1 ; z = yes divide by 2^16 and quit
- div bx
- outlmo1:mov ax,dx ; return remainder in ax
- pop bx
- pop bp
- ret
- _ourlmod endp
-
- ; int ourldiv(long top, int bottom)
- ; Perform 32 bit integer division of 32 bit quotient by 16 bit divisor
- public _ourldiv
- _ourldiv proc near
- push bp
- mov bp,sp
- push bx
- mov ax,[bp+4+0] ; top lower 16 bits
- mov dx,[bp+4+2] ; top upper 16 bits
- mov bx,[bp+4+4] ; bottom
- cmp dx,bx ; about to overflow?
- jae ourldiv1 ; ae = yes, return 0xffffh
- div bx
- xor dx,dx ; clear remainder (high order ret)
- pop bx
- pop bp ; quotient is returned in dx:ax
- ret
- ourldiv1:mov ax,0ffffh ; overflow indication
- xor dx,dx ; clear high order
- pop bx
- pop bp
- ret
- _ourldiv endp
-
- ; long ourlmul(long top, int bottom)
- ; Perform 32 bit integer multiplication of 32 bit multiplicand by 16 bit mult
- public _ourlmul
- _ourlmul proc near
- push bp
- mov bp,sp
- push bx
- push cx
- mov ax,[bp+4+2] ; top upper 16 bits
- mov bx,[bp+4+4] ; bottom
- mul bx
- mov cx,ax ; save product (no overflow noted)
- mov ax,[bp+4+0] ; top lower 16 bits
- mul bx
- adc dx,cx ; new upper 16 bits
- pop cx
- pop bx
- mov sp,bp
- pop bp ; long product is returned in dx:ax
- ret
- _ourlmul endp
-
- ; void * bcopy(src, dest, count)
- ; void *dest, *src;
- ; size_t count;
- ; copy count bytes from src to dest
- public _bcopy
- _bcopy proc near
- push bp
- mov bp,sp
- push es
- push si
- push di
- push cx
- mov ax,ds ; set to same data segment
- mov es,ax
- mov si,[bp+4+0] ; offset of source
- mov di,[bp+4+2] ; offset of destination
- mov cx,[bp+4+4] ; count
- cld
- push di ; push dest address for return
- jcxz bcopy2 ; z = nothing to copy
- or di,di ; is destination NULL?
- jz bcopy2 ; z = yes, don't do a thing
- cmp si,di ; is source after destination?
- ja bcopy1 ; a = yes, no overlap problem
- je bcopy2 ; e = same place, do nothing
- add di,cx ; start at the ends
- dec di
- add si,cx
- dec si
- std ; work backward
- bcopy1: rep movsb
- bcopy2: pop ax ; recover return destination
- cld
- pop cx
- pop di
- pop si
- pop es
- mov sp,bp
- pop bp
- ret
- _bcopy endp
-
- ; void * bcopy(src, dest, count)
- ; void * FAR dest, * FAR src;
- ; size_t count;
- ; copy count bytes from src to dest
- public _bcopyff
- _bcopyff proc near
- push bp
- mov bp,sp
- push es
- push ds
- push si
- push di
- push cx
- push dx
- lds si,dword ptr [bp+4+0] ; source
- les di,dword ptr [bp+4+4] ; destination
- mov cx,[bp+4+8] ; count
- cld
- jcxz bcopyff2 ; z = nothing to copy
- mov ax,ds
- mov dx,es
- or ax,ax ; is destination NULL?
- jz bcopyff2 ; z = yes, don't do a thing
- cmp ax,dx ; is source seg after destination?
- ja bcopyff1 ; a = yes, no overlap problem
- jb bcopyff3 ; b = no, no overlap the other way
- cmp si,di ; is source offset after destination?
- ja bcopyff1 ; a = yes, no overlap problem
- je bcopyff2 ; e = same place, do nothing
- bcopyff3:add di,cx ; start at the ends
- dec di
- add si,cx
- dec si
- std ; work backward
- bcopyff1:rep movsb
- bcopyff2:xor ax,ax ; say null destination
- cld
- pop dx
- pop cx
- pop di
- pop si
- pop ds
- pop es
- mov sp,bp
- pop bp
- ret
- _bcopyff endp
-
-
- ; void * memset(dest, c, count)
- ; void *dest;
- ; char c;
- ; size_t count;
- ; Store count copies of byte c in destination area dest
- public _memset
- _memset proc near
- push bp
- mov bp,sp
- push es
- push di
- push cx
- mov ax,ds ; setup data segment
- mov es,ax
- mov di,[bp+4+0] ; offset of destination
- or di,di ; is it NULL?
- jz memset1 ; z = yes, don't do a thing
- push di ; save dest for return
- mov al,[bp+4+2] ; byte of character c
- mov ah,al
- mov cx,[bp+4+4] ; count
- jcxz memset1 ; z = do nothing
- cld
- shr cx,1
- jnc memset2
- stosb
- memset2:rep stosw
- pop ax ; return pointer to destination
- memset1:pop cx
- pop di
- pop es
- mov sp,bp
- pop bp
- ret
- _memset endp
-
- ; Allocate size bytes from DOS free memory.
- ; void FAR * malloc(size_t size)
- ; Returns FAR pointer in dx:ax, or 0L if failure. Size is an unsigned int.
- public _malloc
- _malloc proc near
- push bp
- mov bp,sp
- push bx
- push cx
- mov bx,[bp+4+0] ; bytes wanted
- add bx,15 ; round up
- mov cl,4
- shr bx,cl ; convert to # of paragraphs
- mov cx,bx ; remember quantity wanted
- mov ah,allocmem ; DOS memory allocator
- int dos ; returns segment in ax
- jc malloc1 ; c = fatal error
- cmp cx,bx ; paragraphs wanted vs delivered
- je malloc2 ; e = got the block
- push es ; insufficient, return it
- mov es,ax ; identify the block
- mov ah,freemem ; free the unwanted block
- int dos
- pop es
- malloc1:xor ax,ax ; return 0L on failure
- malloc2:mov dx,ax ; segment
- xor ax,ax ; offset
- pop cx
- pop bx
- pop bp
- ret
- _malloc endp
-
- ; Free a block of memory allocated from the DOS memory pool.
- ; void free(FAR * memblock);
- public _free
- _free proc near
- push bp
- mov bp,sp
- push ax
- push es
- mov ax,[bp+4+2] ; get high order (segment) arg
- or ax,ax ; NULL?
- jz free1 ; z = yes, leave it alone
- mov es,ax ; identify the block
- mov ah,freemem ; free the unwanted block
- int dos
- free1: pop es
- pop ax
- pop bp
- ret
- _free endp
-
- ; int fstchr(const char FAR * p, word len, byte c)
- ; finds first occurence of unsigned byte in low part of c and returns
- ; the number of bytes preceeding it in the buffer, or len if not found.
- public _fstchr
- _fstchr proc near
- push bp
- mov bp,sp
- push es
- push bx
- push cx
- push di
- les di,dword ptr [bp+4+0] ; Far string address
- mov bx,es ; check for NULL
- mov ax,-1 ; error return value
- or bx,bx ; NULL?
- jz fstchr1 ; z = yes, return -1
- mov bx,di ; remember starting offset
- mov cx,[bp+4+4] ; number of bytes to examine
- jcxz fstchr1 ; z = empty string, return -1
- mov ax,[bp+4+6] ; pattern is in al
- cld
- repne scasb
- mov ax,di ; ending place
- dec ax ; minus auto inc of rep
- sub ax,bx ; minus starting offset
- fstchr1:pop di
- pop cx
- pop bx
- pop es
- pop bp
- ret
- _fstchr endp
-
- ; Timer routines - use set_*timeout to receive a clock value which
- ; can later be tested by calling chk_timeout with
- ; that clock value to determine if a timeout has
- ; occurred. chk_timeout returns 0 if NOT timed out.
- ; Usage: long set_timeout( int seconds );
- ; long set_ttimeout( int bios_ticks );
- ; int chk_timeout( long value );
- ;
- ; (c) 1990 University of Waterloo,
- ; Faculty of Engineering,
- ; Engineering Microcomputer Network Development Office
- ; version
- ; 0.1 7-Nov -1990 E. P. Engelke
-
- public _set_ttimeout
- _set_ttimeout proc near
- push bp
- mov bp,sp
- push es
- xor ax,ax
- cwd
- mov es,ax
- mov ax,[bp+4+0] ; initial Bios clock ticks
- pushf ; critical section
- cli
- add ax,es:[BIOSCLK+0];
- adc dx,es:[BIOSCLK+2];
- popf ; end critical section
- pop es
- pop bp
- ret
- _set_ttimeout endp
-
- public _set_timeout
- _set_timeout proc near
- push bp
- mov bp,sp
- push es
- push cx
- xor ax,ax ; reference low memory
- mov es,ax
- mov ax,[bp+4+0] ; seconds
- xor dx,dx
- mov cx,1165
- mul cx ; 1165/64 = 18.203...
- mov cx,6
- tmp: shr dx,1
- rcr ax,1
- loop tmp
- pushf ; critical section
- cli
- add ax,es:[BIOSCLK+0]
- adc dx,es:[BIOSCLK+2]
- popf ; end critical section
- pop cx
- pop es
- pop bp
- ret
- _set_timeout endp
-
- public _chk_timeout
- _chk_timeout proc near
- push bp
- mov bp,sp
- push cx
- push es
- xor ax,ax
- mov es,ax
- pushf ; critical section
- cli
- mov cx,es:[BIOSCLK+0]
- mov bx,es:[BIOSCLK+2]
- popf ; end critical section
- pop es
- mov ax,[bp+4+0] ; timeout value
- mov dx,[bp+4+2]
- cmp dx,bx ; if timeout < clock, has expired
- jb ret_tru
- cmp ax,cx
- jbe ret_tru
- ; may have gone over by one day
- sub ax,LO_MAX
- sbb dx,HI_MAX
- jc ret_fal ; c = nope, timeout is today
- ; test timeout new values
- cmp dx,bx
- jb ret_tru
- cmp ax,cx
- ja ret_fal
- ret_tru:mov ax,1 ; say have timed out
- pop cx
- pop bp
- ret
-
- ret_fal:xor ax,ax ; say have not timed out
- pop cx
- pop bp
- ret
- _chk_timeout endp
-
- ; unsigned long realclock(void)
- public _realclock
- _realclock proc near ; get Bios time of day dword
- push es
- xor ax,ax ; reference low memory
- mov es,ax
- pushf ; critical section
- cli
- mov ax,es:[BIOSCLK+0] ; return Bios time of day tick count
- mov dx,es:[BIOSCLK+2]
- popf ; end critical section
- pop es
- ret
- _realclock endp
-
- ; void _chkstk()
- ; Stack checker
- ; {
- ; ;
- ; }
- public __chkstk, __aNchkstk
- __chkstk proc near ; MSC v5.1
- __aNchkstk equ this byte ; MSC v6.00
- pop bx ; pop return address
- sub sp,ax ; down adjust stack pointer
- jmp bx ; return the no-stack way
- __chkstk endp
-
- ; Microsoft C v7.0 direct support. Shift left dx:ax by cx. No C calling conv.
- ; Long shift left
- public __aNlshl
- __aNlshl proc near
- jcxz lshift2 ; z = no shift
- lshift1:shl ax,1
- rcl dx,1
- loop lshift1
- lshift2:ret
- __aNlshl endp
-
- ; Microsoft C v7.0 direct support. Shift rgt dx:ax by cx. No C calling conv.
- ; Unsigned long shift right
- public __aNulshr
- __aNulshr proc near
- jcxz rshift2 ; z = no shift
- rshift1:shr dx,1
- rcr ax,1
- loop rshift1
- rshift2:ret
- __aNulshr endp
-
- ; void
- ; outch(char ch)
- ; Sends character to the screen via the msgbuf buffer if operating at
- ; interrupt level, or via DOS if operating at task level.
- public _outch
- _outch proc near
- push bp
- mov bp,sp
- push ax
- push bx
- cmp _display_mode,0 ; quiet screen?
- je outch3 ; e = yes
- mov al,[bp+4] ; get the character
- cmp _doslevel,0 ; at DOS task level?
- je outch1 ; e = no
- mov ah,conout ; use DOS
- push dx
- mov dl,al
- int dos
- pop dx
- jmp short outch3
- outch1: cmp _msgcnt,MSGBUFLEN ; is buffer filled?
- ja outch3 ; a = yes, discard this byte
- mov bx,_msgcnt
- mov _msgbuf[bx],al
- inc _msgcnt
- outch3: pop bx
- pop ax
- mov sp,bp
- pop bp
- ret
- _outch endp
-
-
- ; void
- ; outsn(char * string, int count)
- ; display counted string
- public _outsn
- _outsn proc near
- push bp
- mov bp,sp
- push ax
- push si
- mov si,[bp+4] ; string address
- mov cx,[bp+4+2] ; string length
- cld
- outsn1: lodsb
- or al,al
- jz outsn2
- push ax ; push arg
- call _outch
- pop ax ; clean stack
- loop outsn1
- outsn2: pop si
- pop ax
- mov sp,bp
- pop bp
- ret
- _outsn endp
-
- ; void
- ; outs(char * string)
- ; display asciiz string
- public _outs
- _outs proc near
- push bp
- mov bp,sp
- push ax
- push si
- mov si,[bp+4] ; asciiz string address
- cld
- outs1: lodsb
- or al,al ; terminator ?
- jz outs2 ; z = yes
- push ax ; push arg
- call _outch
- pop ax ; clean stack
- jmp short outs1
- outs2: pop si
- pop ax
- mov sp,bp
- pop bp
- ret
- _outs endp
-
- ; void
- ; outhex(char c)
- ; display char in hex
- public _outhex
- _outhex proc near
- push bp
- mov bp,sp
- push ax
- mov ax,[bp+4] ; incoming character
- mov cl,4
- shr al,cl
- call outh
- mov ax,[bp+4]
- call outh
- pop ax
- mov sp,bp
- pop bp
- ret
-
- ; worker for outhex
- outh proc near
- and al,0fh
- cmp al,9
- jbe outh1
- add al,'A' - '9' - 1
- outh1: add al,'0'
- push ax
- call _outch
- pop ax
- ret
- outh endp
- _outhex endp
-
- ; output a string of hex chars
- ; void
- ; outhexes(char * string, int count )
- public _outhexes
- _outhexes proc near
- push bp
- mov bp,sp
- push ax
- push si ; preserve such things
- mov si,[bp+4] ; get string pointer
- mov cx,[bp+4+2] ; get char count
- jcxz outhexs2 ; z = nothing
- cld
- outhexs1:lodsb ; read a byte
- push cx ; save loop counter
- push ax
- call _outhex ; display as hex pair
- add sp,2 ; clean stack
- pop cx
- loop outhexs1 ; do count's worth
- outhexs2:pop si
- pop ax
- mov sp,bp
- pop bp
- ret
- _outhexes endp
- _TEXT ends
- end
-